﻿using AutoMapper;
using JuCheap.Core.Data.Entity;
using JuCheap.Core.Infrastructure;
using JuCheap.Core.Infrastructure.Exceptions;
using JuCheap.Core.Infrastructure.Extentions;
using JuCheap.Core.Infrastructure.Utilities;
using JuCheap.Core.IRepository;
using JuCheap.Core.IService.AppService;
using JuCheap.Core.Model;
using JuCheap.Core.Model.Message;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace JuCheap.Core.Service.AppService
{
    /// <summary>
    /// 站内信扩展服务
    /// </summary>
    public class MessageService : IMessageService
    {
        private readonly ISysMessageRepository _messageRepository;
        private readonly ISysMessageUserRepository _sysMessageUserRepository;
        private readonly IUnitWork _unitWork;
        private readonly IMapper _mapper;
        private readonly ICurrentUserService _currentUserService;
        private readonly ISysUserRepository _sysUserRepository;

        /// <summary>
        /// ctor
        /// </summary>
        public MessageService(IUnitWork unitWork, 
            ISysMessageRepository messageRepository,
            ISysMessageUserRepository sysMessageUserRepository,
            IMapper mapper,
            ICurrentUserService currentUserService,
            ISysUserRepository sysUserRepository)
        {
            _unitWork = unitWork;
            _messageRepository = messageRepository;
            _sysMessageUserRepository = sysMessageUserRepository;
            _mapper = mapper;
            _currentUserService = currentUserService;
            _sysUserRepository = sysUserRepository;
        }

        /// <summary>
        /// 创建站内信
        /// </summary>
        /// <param name="messageReq">站内信请求内容模型</param>
        /// <returns></returns>
        public async Task<string> CreateAsync(MessageCreateRequestDto messageReq)
        {
            if (!messageReq.ReceiverIds.AnyOne())
            {
                throw new BusinessException("请选择站内信接收人");
            }
            using(var ts = await _unitWork.BeginTransactionAsync())
            {
                var message = _mapper.Map<SysMessage>(messageReq);
                message.SendType = (byte)messageReq.GetSendType();
                message.Sender = _currentUserService.GetCurrentUser().Name;
                var messageId = await _messageRepository.InsertAsync(message);

                //插入接收人的信息
                var userIds = messageReq.ReceiverIds;
                if(messageReq.GetSendType() == MessageType.All)
                {
                    var isSystem = _currentUserService.IsSystemCompany();
                    userIds = await _sysUserRepository.Queryable(!isSystem).Select(x => x.Id).ToListAsync();
                }
                var receivers = userIds.Select(userId => new SysMessageUser
                {
                    MessageId = messageId,
                    ReceiverId = userId,
                    Status = (byte)MessageStatus.UnRead
                }).ToList();
                await _sysMessageUserRepository.BatchInsertAsync(receivers);

                await ts.CommitAsync();
                return messageId;
            }
        }

        /// <summary>
        /// 获取站内信详细信息
        /// </summary>
        /// <param name="messageId">站内信Id</param>
        /// <returns></returns>
        public async Task<MyMessageResponseDto> GetAsync(string messageId)
        {
            return await _messageRepository.Queryable(false).Where(x => x.Id == messageId)
                .Select(x => new MyMessageResponseDto
                {
                    Id = x.Id,
                    Title = x.Title,
                    Contents = x.Contents,
                    Sender = x.Sender,
                    SendTime = x.CreateTime
                }).FirstOrDefaultAsync();
        }

        /// <summary>
        /// 阅读
        /// </summary>
        /// <param name="messageIds">站内信Id</param>
        /// <param name="userId">用户Id</param>
        /// <returns></returns>
        public async Task ReadAsync(IList<string> messageIds, string userId)
        {
            if (!messageIds.AnyOne())
            {
                return;
            }
            var receivers = await _sysMessageUserRepository.Queryable(false)
                .Where(x => messageIds.Contains(x.MessageId) && x.ReceiverId == userId && x.Status == (byte)MessageStatus.UnRead).ToListAsync();
            foreach(var receiver in receivers)
            {
                var user = _currentUserService.GetCurrentUser();
                receiver.Read(user);
                await _sysMessageUserRepository.UpdateAsync(receiver);
            }
        }

        /// <summary>
        /// 获取我的站内信
        /// </summary>
        public async Task<PagedResult<MyMessageResponseDto>> GetMyMessagesAsync(SysMessageFilter filter)
        {
            filter.PreHandle();

            var isSendByMe = filter.QueryType.HasValue && filter.QueryType.Value == MessageQueryType.SendByMe;
            IQueryable<MyMessageResponseDto> query = null;
            if (isSendByMe)
            {
                query = from message in _messageRepository.Queryable(false)
                        where message.CreateUserId == filter.UserId
                        select new MyMessageResponseDto
                        {
                            Id = message.Id,
                            Sender = message.Sender,
                            SendTime = message.CreateTime,
                            Title = message.Title,
                            Contents = message.Contents,
                            SendType = message.SendType
                        };
            }
            else
            {
                query = from message in _messageRepository.Queryable(false)
                        join receiver in _sysMessageUserRepository.Queryable(false) on message.Id equals receiver.MessageId
                        where receiver.ReceiverId == filter.UserId
                        select new MyMessageResponseDto
                        {
                            Id = message.Id,
                            Sender = message.Sender,
                            SendTime = message.CreateTime,
                            Title = message.Title,
                            Contents = message.Contents,
                            SendType = message.SendType,
                            Status = receiver.Status,
                            ReadDate = receiver.ReadTime
                        };

                query = query.WhereIf(filter.Status.HasValue, x => x.Status == (byte)filter.Status.Value);
            }

            query = query.WhereIf(filter.Title.IsNotBlank(), x => x.Title.Contains(filter.Title));
            return await query.QueryPagesAsync(filter);
        }

        /// <summary>
        /// 获取我未读站内信数量
        /// </summary>
        /// <param name="userId">用户Id</param>
        /// <returns></returns>
        public async Task<int> GetMyMessageUnReadNumberAsync(string userId)
        {
            var query = from message in _messageRepository.Queryable(false)
                        join receiver in _sysMessageUserRepository.Queryable(false) on message.Id equals receiver.MessageId
                        where receiver.ReceiverId == userId && receiver.Status == (byte)MessageStatus.UnRead
                        select message.Id;
            return await query.CountAsync();

        }
    }
}
